﻿namespace IBTrader.Charts
{
    using IBTrader.Modules.Read;
    using NLog;
    using System;
    using System.Collections.Generic;
    using System.Linq;

    class Region
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
        internal readonly Point X, Y;
        public Region(IGrouping<int, IChart>[] regions, IGrouping<int, IChart> group, int index, double width, double height)
        {
            var heights = Region.Heights(regions, index, height);
            var lines = group.SelectMany(g => g.Lines.ToArray());
            X = new Point(lines.Select(l => l.DateTime.TimeOfDay.TotalSeconds), width, 0);
            Y = new Point(lines.Select(l => l.Price), heights[0], heights[1]);
            //logger.Debug("X {0} Y {1} r: {2} #: {3} i: {4}", X, Y, regions.Length, group.Count(), index);
        }
        public float x(Line line)
        {
            return (float)((line.DateTime.TimeOfDay.TotalSeconds - X.Min) / X.Pixel + X.Offset);
        }
        public float y(Line line) { return y(line.Price); }
        public float y(double price)
        {
            return (float)Indicator.Base.NaN((Y.Max - price) / Y.Pixel + Y.Offset);
        }
        public class Point
        {
            public readonly float Min, Max, Pixel, Total, Offset;
            public Point(IEnumerable<double> values, double total, double offset)
            {
                if (!values.Any()) return;
                Total = (float)total;
                Offset = (float)offset;
                Min = (float)values.Min();
                Max = (float)values.Max();
                Pixel = (float)(Math.Max(1,(Max - Min)) / Total); // avoid 0=>NaN
            }
            public double Interval(IEnumerable<double> values)
            {
                var intervals = Math.Max(3, (int)Total / 50);
                var distance = values.Max() - values.Min();
                var interval = distance / intervals;
                return interval;
            }
            public double Interval(IEnumerable<long> values)
            {
                var intervals = Math.Max(3, (int)Total / 50);
                var distance = values.Max() - values.Min();
                var interval = distance / intervals;
                return interval;
            }
            public override string ToString()
            {
                return string.Format("Min {0} Max {1} Pixel {2} Total {3} Offset {4}", Min, Max, Pixel, Total, Offset);
            }
        }
        private static double[] Heights(IGrouping<int, IChart>[] regions, int i, double height)
        {
            var childs = regions.Length - 1;
            var regionHeight = childs == 0 ? 0 : Math.Min(height * .6f, height * .1f * childs) / childs; // between max+min

            return (i == 0) // main region
                ? new[] { height - regionHeight * childs, 0 }
                : new[] { regionHeight, height - regionHeight * i };
        }
    }
}